package hikari.gui.panels;

import com.gooddies.events.ValueChangedEvent;
import com.gooddies.texteditors.DefaultFloatTextField;
import com.gooddies.wiring.annotations.WiringComponent;
import hikari.gui.guicomponents.ColorPicker;
import hikari.gui.guicomponents.hLabel;
import hikari.hcomponents.HComponent;
import hikari.hcomponents.RenderEvent;
import hikari.objects3d.light.ConeLight3dObject;
import hikari.objects3d.light.Light3dObject;
import java.awt.Color;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import net.miginfocom.swing.MigLayout;
import org.swig.jirr.ILightSceneNode;
import org.swig.jirr.SColor;
import org.swig.jirr.SColorf;
import org.swig.jirr.SLight;

/**
 * @author Dmitry
 */
@WiringComponent(singleton = true, lazy = true)
public class LightPanel extends HComponent {

    private static LightPanel instance;
    private DefaultFloatTextField radiusEditBox;
    private DefaultFloatTextField outerConeAngleEditBox;
    private DefaultFloatTextField innerConeAngleEditBox;
    private DefaultFloatTextField fallofEditBox;
    private ColorPicker ambientColorPicker;
    private ColorPicker diffuseColorPicker;
    private ColorPicker specularColorPicker;
    private Light3dObject light;
    private List<JComponent> coneComponents = new ArrayList<>();

    private LightPanel() {
        setTitle("Light Settings");
        setLayout(new MigLayout("insets 5"));
        add(new hLabel("Radius"));
        radiusEditBox = new DefaultFloatTextField(0, 9999999);
        radiusEditBox.setValueChangedEventNumber(new ValueChangedEvent<Float>() {
            @Override
            public void valueChanged(Float value) {
                light.getLightNode().setRadius(value);
            }
        });
        add(radiusEditBox, "w 150!,spanx 10, wrap");
        add(new hLabel("Ambient color"), "spanx 2");
        ambientColorPicker = new ColorPicker();
        ambientColorPicker.setValueChangedEvent(new ValueChangedEvent<Color>() {
            @Override
            protected void valueChanged(Color color) {
                light.getLightNode().getLightData().setAmbientColor(new SColorf(new SColor(color)));
            }
        });
        add(ambientColorPicker, "wrap");
        add(new hLabel("Diffuse color"), "spanx 2");
        diffuseColorPicker = new ColorPicker();
        diffuseColorPicker.setValueChangedEvent(new ValueChangedEvent<Color>() {
            @Override
            protected void valueChanged(Color value) {
                light.getLightNode().getLightData().setDiffuseColor(new SColorf(new SColor(value)));
            }
        });
        add(diffuseColorPicker, "wrap");
        add(new hLabel("Specular color"), "spanx 2");
        specularColorPicker = new ColorPicker();
        specularColorPicker.setValueChangedEvent(new ValueChangedEvent<Color>() {
            @Override
            protected void valueChanged(Color color) {
                light.getLightNode().getLightData().setSpecularColor(new SColorf(new SColor(color)));
            }
        });
        add(specularColorPicker, "wrap");
        fallofEditBox = new DefaultFloatTextField();
        fallofEditBox.setValueChangedEventNumber(new ValueChangedEvent<Float>() {
            @Override
            public void valueChanged(Float value) {
                light.getLightNode().getLightData().setFalloff(value);
            }
        });
        hLabel label = new hLabel("Fallof");
        add(label);
        add(fallofEditBox, "spanx 10, w 80!, wrap");
        label = new hLabel("Outer cone angle");
        add(label, "spanx 10");
        coneComponents.add(label);
        outerConeAngleEditBox = new DefaultFloatTextField(0, 180);
        outerConeAngleEditBox.setValueChangedEventNumber(new ValueChangedEvent<Float>() {
            @Override
            public void valueChanged(Float value) {
                light.getLightNode().getLightData().setOuterCone(value);
            }
        });
        add(outerConeAngleEditBox, "w 50!, wrap");
        coneComponents.add(outerConeAngleEditBox);
        label = new hLabel("Inner cone angle");
        add(label, "spanx 10");
        coneComponents.add(label);
        innerConeAngleEditBox = new DefaultFloatTextField(0, 180);

        innerConeAngleEditBox.setValueChangedEventNumber(new ValueChangedEvent<Float>() {
            @Override
            public void valueChanged(Float value) {
                light.getLightNode().getLightData().setInnerCone(value);
            }
        });
        add(innerConeAngleEditBox, "w 50!, wrap");
        coneComponents.add(innerConeAngleEditBox);
    }

    public LightPanel initialUpdateFromModel(Light3dObject model) {
        update(model);
        light = model;
        return this;
    }

    private void update(Light3dObject model) {
        ILightSceneNode tlight = model.getLightNode();
        SLight data = tlight.getLightData();
        boolean showConeComponents = (model instanceof ConeLight3dObject);
        for (JComponent component : coneComponents) {
            component.setVisible(showConeComponents);
        }
        radiusEditBox.setValue(data.getRadius());
        outerConeAngleEditBox.setValue(data.getOuterCone());
        innerConeAngleEditBox.setValue(data.getInnerCone());
        fallofEditBox.setValue(data.getFalloff());
        ambientColorPicker.setSelectedColor(data.getAmbientColor().toSColor());
        diffuseColorPicker.setSelectedColor(data.getDiffuseColor().toSColor());
        specularColorPicker.setSelectedColor(data.getSpecularColor().toSColor());
        revalidate();
        validate();
        repaint();
    }

    @Override
    public RenderEvent registerAfterRenderBeforeGuiEvent() {
        return new RenderEvent() {
            @Override
            public void onRender() {
                if (light != null) {
                    light.drawGizmos();
                }
            }
        };
    }
}
